//////////////////////////////////////////////////////////////////////////

#ifndef _OBSERVER_H_
#define _OBSERVER_H_

//////////////////////////////////////////////////////////////////////////

#include <set>

//////////////////////////////////////////////////////////////////////////

class Observable;

//////////////////////////////////////////////////////////////////////////


/** This class implements Observer design pattern
*
*   Usage: 
*   1. Create a subclass of Observer and implement OnEvent() method;
*   2. Add desired events to observe;
*   3. Pass a pointer (this) to AddObserver method() in the Observable
*      object to make the observer work;
*   4. Pass a pointer (this) to RemoveObserver method() in the Observable
*      object to stop observing.
*
*  @author   Roman Pasechnik
*  @since    Aug 04th, 2009
*  @updated  Jan 22th, 2010
*/
class Observer
{
//////////////////////////////////////////////////////////////////////////

public:

//////////////////////////////////////////////////////////////////////////


    /** Destructor */
    virtual ~Observer()
    {
    };


//////////////////////////////////////////////////////////////////////////


    /** Events, that can be handled by observer */
    enum Event
    {
        KEY_INPUT_CHANGE,
        MOUSE_POSITION_CHANGE,

        NETWORK_RECEIVE_COMPLETE_TCP,
        NETWORK_RECEIVE_COMPLETE_UDP,
        NETWORK_SEND_COMPLETE_TCP,
        NETWORK_SEND_COMPLETE_UDP,
        NETWORK_ACCEPTED_NEW_CONNECTION,
        NETWORK_DISCONNECT
    };


//////////////////////////////////////////////////////////////////////////


    /** Notifies observer about event.
        NOTE: You need to implement this in subclass if you want to use
        the observer */
    virtual void OnEvent( Event _event, Observable* _observable ) = 0;


//////////////////////////////////////////////////////////////////////////


    /** Adds an event to observe */
    void AddEventToObserve( Event _event )
    {
        m_EventsToObserve.insert(_event);
    }


//////////////////////////////////////////////////////////////////////////


    /** Checks, if object observes this event.
        This function is called by Observable. */
    bool IsEventToObserve( Event _event ) const
    {
        Events::const_iterator it = m_EventsToObserve.find(_event);
        return it != m_EventsToObserve.end();
    }


//////////////////////////////////////////////////////////////////////////

private:

//////////////////////////////////////////////////////////////////////////


    /** [Utility type]: a set of events */
    typedef std::set<Event> Events;


    /** All events to observe */
    Events m_EventsToObserve;


//////////////////////////////////////////////////////////////////////////
};


//////////////////////////////////////////////////////////////////////////

#endif

//////////////////////////////////////////////////////////////////////////

